package com.fourierlab.ibator.plugins;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

import org.apache.commons.lang.StringUtils;
import org.apache.ibatis.ibator.api.GeneratedJavaFile;
import org.apache.ibatis.ibator.api.GeneratedXmlFile;
import org.apache.ibatis.ibator.api.IbatorPluginAdapter;
import org.apache.ibatis.ibator.api.IntrospectedTable;
import org.apache.ibatis.ibator.api.dom.java.TopLevelClass;
import org.apache.ibatis.ibator.api.dom.xml.Attribute;
import com.fourierlab.ibator.plugins.Document;
import org.apache.ibatis.ibator.api.dom.xml.XmlElement;
import org.apache.ibatis.ibator.internal.util.StringUtility;
import org.apache.ibatis.ibator.internal.util.messages.Messages;

public class SpringAppContextPlugin extends IbatorPluginAdapter {
	private Map<String, String> maps = new TreeMap<String, String>();
	
	public SpringAppContextPlugin() {
		super();
	}

	public boolean validate(List<String> warnings) {
        boolean valid = true;
        
        if (!StringUtility.stringHasValue(properties.getProperty("targetProject"))) {
            warnings.add(Messages.getString("Warning.25"));
            valid = false;
        }
        
        if (!StringUtility.stringHasValue(properties.getProperty("targetPackage"))) {
            warnings.add(Messages.getString("Warning.26"));
            valid = false;
        }
        
        if (!StringUtility.stringHasValue(properties.getProperty("targetExtPackage"))) {
            warnings.add(Messages.getString("Warning.26"));
            valid = false;
        }
        
        return valid;
	}

	/* (non-Javadoc)
	 * @see org.apache.ibatis.ibator.api.IbatorPluginAdapter#contextGenerateAdditionalXmlFiles()
	 */
	@Override
	public List<GeneratedXmlFile> contextGenerateAdditionalXmlFiles() {
        Document document = new Document();
        XmlElement root = new XmlElement("beans");
        root.addAttribute(new Attribute("xmlns", "http://www.springframework.org/schema/beans"));
        root.addAttribute(new Attribute("xmlns:context", "http://www.springframework.org/schema/context"));
        root.addAttribute(new Attribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance"));
        root.addAttribute(new Attribute("xmlns:aop", "http://www.springframework.org/schema/aop"));
        root.addAttribute(new Attribute("xmlns:tx", "http://www.springframework.org/schema/tx"));
        root.addAttribute(new Attribute("xsi:schemaLocation", "http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"));
        document.setRootElement(root);
        
//        for (TopLevelClass topLevelClass : daoImplClasses) {
//			XmlElement beanElement = new XmlElement("bean");
//			beanElement.addAttribute(new Attribute("id", calculateId(topLevelClass)));
//			beanElement.addAttribute(new Attribute("class", topLevelClass.getType().getFullyQualifiedName()));
//			XmlElement propertyElement = new XmlElement("property");
//			propertyElement.addAttribute(new Attribute("name", "sqlMapClientTemplate"));
//			propertyElement.addAttribute(new Attribute("ref", "sqlMapClientTemplate"));
//			beanElement.addElement(propertyElement);
//			root.addElement(beanElement);
//		}

        for (String id : maps.keySet()) {
			XmlElement beanElement = new XmlElement("bean");
			beanElement.addAttribute(new Attribute("id", id));
			beanElement.addAttribute(new Attribute("class", maps.get(id)));
			XmlElement propertyElement = new XmlElement("property");
			propertyElement.addAttribute(new Attribute("name", "sqlMapClientTemplate"));
			propertyElement.addAttribute(new Attribute("ref", "sqlMapClientTemplate"));
			beanElement.addElement(propertyElement);
			root.addElement(beanElement);
		}
        
        GeneratedXmlFile gxf = new GeneratedXmlFile(document,
                properties.getProperty("fileName", "DaoAppCtx.xml"),
                properties.getProperty("targetExtPackage"),
                properties.getProperty("targetProject"),
                false);
        
        List<GeneratedXmlFile> answer = new ArrayList<GeneratedXmlFile>(1);
        answer.add(gxf);
        
        return answer;
	}

	/* (non-Javadoc)
	 * @see org.apache.ibatis.ibator.api.IbatorPluginAdapter#initialized(org.apache.ibatis.ibator.api.IntrospectedTable)
	 */
	@Override
	public void initialized(IntrospectedTable introspectedTable) {
		super.initialized(introspectedTable);
		maps.put(calculateId(introspectedTable), calculateClass(introspectedTable));
	}
	
	private String calculateId(IntrospectedTable introspectedTable) {
		String id = String.format(properties.getProperty(DaoPlugin.DAO_IMPL_PATTERN, DaoPlugin.DEFAULT_DAO_IMPL_PATTERN), introspectedTable.getFullyQualifiedTable().getDomainObjectName());
		return StringUtils.uncapitalize(id.replaceAll(properties.getProperty("trimSuffix", "") + "$", ""));
	}
	
	private String calculateClass(IntrospectedTable introspectedTable) {
		return properties.getProperty("targetExtPackage") + "." + String.format(properties.getProperty(DaoPlugin.DAO_IMPL_PATTERN, DaoPlugin.DEFAULT_DAO_IMPL_PATTERN), introspectedTable.getFullyQualifiedTable().getDomainObjectName());
	}
}
